package com.wlcb.jpower.chat.config.wx.mp;

import cn.hutool.core.date.DatePattern;
import com.wlcb.jpower.chat.entity.wxapp.TblWxApp;
import com.wlcb.jpower.chat.message.handler.*;
import com.wlcb.jpower.chat.service.wx.mp.WxAppService;
import com.wlcb.jpower.constant.DBConstant;
import com.wlcb.jpower.constant.RedisEunm;
import com.wlcb.jpower.module.common.utils.DateUtil;
import com.wlcb.jpower.module.common.utils.Fc;
import com.wlcb.jpower.utils.CreateJedisOps;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.mp.api.WxMpMessageRouter;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.api.impl.WxMpServiceImpl;
import me.chanjar.weixin.mp.config.impl.WxMpDefaultConfigImpl;
import me.chanjar.weixin.mp.config.impl.WxMpRedisConfigImpl;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;

import java.io.File;
import java.util.List;
import java.util.stream.Collectors;

import static me.chanjar.weixin.common.api.WxConsts.EventType;
import static me.chanjar.weixin.common.api.WxConsts.EventType.SUBSCRIBE;
import static me.chanjar.weixin.common.api.WxConsts.EventType.UNSUBSCRIBE;
import static me.chanjar.weixin.common.api.WxConsts.XmlMsgType;
import static me.chanjar.weixin.common.api.WxConsts.XmlMsgType.EVENT;
import static me.chanjar.weixin.mp.constant.WxMpEventConstants.CustomerService.KF_CLOSE_SESSION;
import static me.chanjar.weixin.mp.constant.WxMpEventConstants.CustomerService.KF_CREATE_SESSION;
import static me.chanjar.weixin.mp.constant.WxMpEventConstants.CustomerService.KF_SWITCH_SESSION;
import static me.chanjar.weixin.mp.constant.WxMpEventConstants.POI_CHECK_NOTIFY;

/**
 * @description: 微信公众平台配置类
 * @author: liwenfei
 * @time: 2021/2/2 10:15
 */
@Slf4j
@Configuration
@AllArgsConstructor
public class WxMpConfiguration {

    @Autowired
    private WxAppService wxAppService;
    @Autowired
    private Environment env;

    private final LogHandler logHandler;
    private final NullHandler nullHandler;
    private final KfSessionHandler kfSessionHandler;
    private final StoreCheckNotifyHandler storeCheckNotifyHandler;
    private final LocationHandler locationHandler;
    private final MenuHandler menuHandler;
    private final MsgHandler msgHandler;
    private final UnsubscribeHandler unsubscribeHandler;
    private final SubscribeHandler subscribeHandler;
    private final ScanHandler scanHandler;
    private final ScancodePushHandler scancodePushHandler;
    private final SubscribeMsgPopupHandler subscribeMsgPopupHandler;


    @Bean
    public WxMpService wxMpService() {
        String host = env.getProperty("spring.redis.host");
        String port = env.getProperty("spring.redis.port");
        String password = env.getProperty("spring.redis.password");
        String database = env.getProperty("spring.redis.database");
        String fileParentPath = env.getProperty("jpowerchat.file-path");

        List<TblWxApp> wxApps = wxAppService.findByStaus(DBConstant.EnableEnum.OPEN.getType());
        WxMpService wxMpService = new WxMpServiceImpl();
        if (Fc.isNotEmpty(wxApps)) {
            CreateJedisOps.Ops ops = CreateJedisOps.Ops.builder()
                    .config(new GenericObjectPoolConfig())
                    .host(host)
                    .port(Integer.valueOf(port))
                    .timeout(3000)
                    .password(password)
                    .database(Integer.valueOf(database))
                    .ssl(false).build();
            wxMpService.setMultiConfigStorages(wxApps.stream().map(x -> {
                WxMpDefaultConfigImpl configStorage = new WxMpRedisConfigImpl(CreateJedisOps.getInstance(ops), RedisEunm.WX_MP.getKeyPrefix());
                configStorage.setSecret(x.getAppSecret());
                configStorage.setAesKey(x.getAesKey());
                configStorage.setAppId(x.getAppId());
                configStorage.setToken(x.getToken());
                File parentPath = new File(fileParentPath + x.getAppId() + File.separator + DateUtil.format(DateUtil.date(), DatePattern.PURE_DATE_FORMATTER));
                if (!parentPath.exists()) {
                    parentPath.mkdirs();
                }
                configStorage.setTmpDirFile(parentPath);
                return configStorage;
            }).collect(Collectors.toMap(WxMpDefaultConfigImpl::getAppId, a -> a, (o, n) -> o)));
        }
        return wxMpService;
    }

    @Bean
    public WxMpMessageRouter messageRouter(WxMpService wxMpService) {
        final WxMpMessageRouter newRouter = new WxMpMessageRouter(wxMpService);

        // 记录所有事件的日志 （异步执行）
        newRouter.rule().handler(this.logHandler).next();

        // 接收客服会话管理事件
        newRouter.rule().async(false).msgType(EVENT).event(KF_CREATE_SESSION)
                .handler(this.kfSessionHandler).end();

        newRouter.rule().async(false).msgType(EVENT).event(KF_CLOSE_SESSION)
                .handler(this.kfSessionHandler).end();

        newRouter.rule().async(false).msgType(EVENT).event(KF_SWITCH_SESSION)
                .handler(this.kfSessionHandler).end();

        // 门店审核事件
        newRouter.rule().async(true).msgType(EVENT).event(POI_CHECK_NOTIFY).handler(this.storeCheckNotifyHandler).end();

        // 自定义菜单事件
        newRouter.rule().async(false).msgType(EVENT).event(EventType.CLICK).handler(this.menuHandler).end();

        // 扫码事件 SCANCODE_PUSH
        newRouter.rule().async(true).msgType(EVENT).event(EventType.SCANCODE_PUSH).handler(this.scancodePushHandler).end();

        // 点击菜单链接事件
        newRouter.rule().async(false).msgType(EVENT).event(EventType.VIEW).handler(this.nullHandler).end();

        // 关注事件
        newRouter.rule().async(true).msgType(EVENT).event(SUBSCRIBE).handler(this.subscribeHandler).end();

        // 取消关注事件
        newRouter.rule().async(true).msgType(EVENT).event(UNSUBSCRIBE).handler(this.unsubscribeHandler).end();

        // 上报地理位置事件
        newRouter.rule().async(true).msgType(EVENT).event(EventType.LOCATION).handler(this.locationHandler).end();

        // 接收地理位置消息
        newRouter.rule().async(true).msgType(XmlMsgType.LOCATION).handler(this.locationHandler).end();

        // 扫码事件
        newRouter.rule().async(true).msgType(EVENT).event(EventType.SCAN).handler(this.scanHandler).end();

        // 扫码事件
        newRouter.rule().async(false).msgType(EVENT).event("subscribe_msg_popup_event").handler(this.subscribeMsgPopupHandler).end();
        // 默认的handler  均经过 该handler
        newRouter.rule().async(true).handler(this.msgHandler).end();

        return newRouter;
    }
}
